/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.je.justforme.http;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;

/**
 *
 * @author jeddy
 */
public class HttpHelper {

    private DefaultHttpClient httpClient = new DefaultHttpClient();
    private HttpContext localContext = new BasicHttpContext();
    private Properties props = null;
    private final Logger log = Logger.getLogger(HttpHelper.class.getSimpleName());

    public HttpHelper() {
        init();
    }

    public void clearCookies() {
        httpClient.getCookieStore().clear();
    }

    public JSONObject getJson(String url) {
        HttpGet get = new HttpGet(url);

        try {
            HttpResponse resp = httpClient.execute(get, localContext);
            String data = respToString(resp);
            return new JSONObject(data);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return new JSONObject();
    }

    private void init() {
        //setup cookies
        props = DefaultProperties.getDefaultProps();
    }

    private Map<String, String> getStaticFormData() {
        Map<String, String> ret = new HashMap<String, String>();
        String val = (String) props.get(DefaultProperties.PROP_STATIC_FORM_DATA);
        if (val != null && !val.isEmpty()) {
            String[] args = val.split(";");
            for (String arg : args) {
                String[] kvp = arg.split(":");
                if (kvp.length == 2) {
                    ret.put(kvp[0], kvp[1]);
                } else {
                    log.warning("Static form entry[" + arg + "]: does not have the expected format of key:value");
                }

            }
        }

        return ret;
    }

    public void postJson(String url, JSONObject json) throws UnsupportedEncodingException, IOException {
        HttpPost post = new HttpPost(url);
        post.setHeader("Content-type", "application/json");
        StringEntity payload = new StringEntity(json.toString());
        post.setEntity(payload);
        HttpResponse resp = httpClient.execute(post, localContext);
        printResp(resp);
    }

    public void login() throws Exception {
        HttpPost post = new HttpPost(props.getProperty(DefaultProperties.PROP_AUTH_URL));
        List<NameValuePair> pairs = new ArrayList<NameValuePair>();
        pairs.add(new BasicNameValuePair(props.getProperty(DefaultProperties.PROP_UNAME_FORM_ID), props.getProperty(DefaultProperties.PROP_UNAME)));
        pairs.add(new BasicNameValuePair(props.getProperty(DefaultProperties.PROP_PASSWORD_FORM_ID), props.getProperty(DefaultProperties.PROP_PASSWORD)));
        //log.info("Logging in with username: " + props.getProperty(DefaultProperties.PROP_UNAME) + " pass:" + props.getProperty(DefaultProperties.PROP_PASSWORD));
        Map<String, String> formData = getStaticFormData();
        for (String key : formData.keySet()) {
            pairs.add(new BasicNameValuePair(key, formData.get(key)));
        }
        post.setEntity(new UrlEncodedFormEntity(pairs));
        HttpResponse resp = httpClient.execute(post, localContext);
        Header hdr = resp.getFirstHeader("X-autherrorcode");
        try {
            EntityUtils.consume(resp.getEntity());
        } catch (IOException ex) {
            Logger.getLogger(HttpHelper.class.getName()).log(Level.SEVERE, null, ex);
        }
        // on a login, the site actually results 200, but sets this header to -1. This is how we determine if login is invalid
        if ("-1".equals(hdr.getValue().trim())){
            throw new Exception("Invalid username or password.");
        }
    }

    private String respToString(HttpResponse response) throws IOException {
        HttpEntity entity = response.getEntity();
        StringBuilder sb = new StringBuilder();

        if (entity != null) {
            System.out.println("Response content length: " + entity.getContentLength());
            BufferedReader br = new BufferedReader(new InputStreamReader(entity.getContent()));
            String line = null;
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
        }

        try {
            EntityUtils.consume(entity);
        } catch (IOException ex) {
            Logger.getLogger(HttpHelper.class.getName()).log(Level.SEVERE, null, ex);
        }
        return sb.toString();

    }

    private void printResp(HttpResponse response) {
        HttpEntity entity = response.getEntity();

        System.out.println("----------------------------------------");
        System.out.println(response.getStatusLine());
        if (entity != null) {
            System.out.println("Response content length: " + entity.getContentLength());
        }
        try {
            EntityUtils.consume(entity);
        } catch (IOException ex) {
            Logger.getLogger(HttpHelper.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public void logout() {
        clearCookies();
        httpClient.getConnectionManager().shutdown();
    }
}
